
#include "scorekeeperscreen.h"
#include "ui_scorekeeperscreen.h"
#include "stdio.h"
#include "stdlib.h"
#include "viewplayerstats.h"


ScoreKeeperScreen::ScoreKeeperScreen(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ScoreKeeperScreen)
{
    ui->setupUi(this);
    ui->pitchGroupBox->setVisible(false);
    ui->inPlayGroupBox->setVisible(false);


    //initializing teams for testing purposes
    QVector<Player*> home, away;

    for(int i=0; i<9; i++){
        Player* pHome= new Player();
        pHome->setJerseyNumber(i);
        pHome->setFirstName(QString("home"));
        pHome->setLastName(QString::number(i));
        home.push_back(pHome);
        Player* pAway= new Player();
        pAway->setJerseyNumber(i+9);
        pAway->setFirstName(QString("away"));
        pAway->setLastName(QString::number(i+9));
        away.push_back(pAway);
    }

    keeper=new ScoreKeeper(home, 8, away, 8);
    theScene = new QGraphicsScene();

    int width = ui->graphicsView->geometry().width();
    int height = ui->graphicsView->geometry().height();
    theScene->setSceneRect(0, 0, width,height);
    // turn off the scrollbar in graphicsview
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    //sets up bases
    homeBase=new Base();
    homeBase->setX(354); homeBase->setY(549);
    theScene->addItem(homeBase);
    firstBase=new Base();
    firstBase->setX(516); firstBase->setY(368);
    theScene->addItem(firstBase);
    secondBase=new Base();
    secondBase->setX(354); secondBase->setY(207);
    theScene->addItem(secondBase);
    thirdBase=new Base();
    thirdBase->setX(176); thirdBase->setY(368);
    theScene->addItem(thirdBase);

    // Tell myGraphicsView that this is my scene
    ui->graphicsView->setScene(theScene);

    // Set this to refresh the full viewport whenever any object moves.
    // There are different modes you can set to reduce how frequently
    // you refresh the screen.
    ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    updateValues();

    //setting up memento for saving states
   undoer = new Memento();
}

ScoreKeeperScreen::ScoreKeeperScreen(QVector<Player *> homeLineup, int homePitcher, QVector<Player *> awayLineup, int awayPitcher):
    QWidget(0), ui(new Ui::ScoreKeeperScreen)
{
    ui->setupUi(this);
    ui->pitchGroupBox->setVisible(false);
    ui->inPlayGroupBox->setVisible(false);


    //initializing teams for testing purposes
    QVector<Player*> home, away;

    home = homeLineup;
    away = awayLineup;

    keeper=new ScoreKeeper(home, homePitcher, away, awayPitcher);
    theScene = new QGraphicsScene();

    int width = ui->graphicsView->geometry().width();
    int height = ui->graphicsView->geometry().height();
    theScene->setSceneRect(0, 0, width,height);
    // turn off the scrollbar in graphicsview
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    //sets up bases
    homeBase=new Base();
    homeBase->setX(354); homeBase->setY(549);
    theScene->addItem(homeBase);
    firstBase=new Base();
    firstBase->setX(516); firstBase->setY(368);
    theScene->addItem(firstBase);
    secondBase=new Base();
    secondBase->setX(354); secondBase->setY(207);
    theScene->addItem(secondBase);
    thirdBase=new Base();
    thirdBase->setX(176); thirdBase->setY(368);
    theScene->addItem(thirdBase);

    // Tell myGraphicsView that this is my scene
    ui->graphicsView->setScene(theScene);

    // Set this to refresh the full viewport whenever any object moves.
    // There are different modes you can set to reduce how frequently
    // you refresh the screen.
    ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    updateValues();

    //setting up memento for saving states
   undoer = new Memento();
}

ScoreKeeperScreen::~ScoreKeeperScreen()
{
    delete ui;
}

//updates the labels on top of the screen
void ScoreKeeperScreen::updateValues(){
    QString inningPrefix;
    if(keeper->isBottomHalf()){
        inningPrefix="bottom ";
    }
    else{
        inningPrefix="top ";
    }
    ui->inningValueLabel->setText(inningPrefix.append(QString::number(keeper->getInning())));
    ui->outValueLabel->setText(QString::number(keeper->getOuts()));
    ui->strikesValueLabel->setText(QString::number(keeper->getStrikes()));
    ui->ballsValueLabel->setText(QString::number(keeper->getBalls()));
    ui->AtBatLabel->setText(keeper->whosAtBat()->lastName + " " +  QString::number(keeper->whosAtBat()->getJerseyNumber()));
    ui->homeScoreLabel->setText(QString::number(keeper->getHomeScore()));
    ui->awayScoreLabel->setText(QString::number(keeper->getAwayScore()));
}

//increments strikes and resets widgets
void ScoreKeeperScreen::strike(){
    undoer->saveState(keeper, &playersOnField);
    keeper->incrementStrikes();
    updateValues();
    ui->pitchGroupBox->setVisible(false);
    ui->pitchButton->show();
}

//updates foul value and resets widget
void ScoreKeeperScreen::foul(){
    undoer->saveState(keeper, &playersOnField);
    keeper->foulBall();
    updateValues();
    ui->pitchGroupBox->setVisible(false);
    ui->pitchButton->show();
}

//increments ball value. If it is a walk, then a player will be spawned and placed on first base, pushing other players forward.
void ScoreKeeperScreen::ball(){
    undoer->saveState(keeper, &playersOnField);
    if(keeper->getBalls()==3){
        spawnPlayer();
    }
    if(keeper->incrementBalls()){
        if(keeper->whosOnFirst()!=0){
            if(keeper->whosOnSecond()!=0){
                if(keeper->whosOnThird()!=0){
                    playersOnField.at(0)->~QGraphicsItem();
                    playersOnField.removeAt(0);
                    updateKeeperBases(playersOnField.at(0)->getPlayer());
                    playersOnField.at(0)->setX(thirdBase->x()); playersOnField.at(0)->setY(thirdBase->y());
                    keeper->setThird(playersOnField.at(0)->getPlayer());
                    playersOnField.at(1)->setX(secondBase->x()); playersOnField.at(1)->setY(secondBase->y());
                    keeper->setSecond(playersOnField.at(1)->getPlayer());
                    playersOnField.at(2)->setX(firstBase->x()); playersOnField.at(2)->setY(firstBase->y());
                    keeper->setFirst(playersOnField.at(2)->getPlayer());
                }
                else{
                    playersOnField.at(0)->setX(thirdBase->x()); playersOnField.at(0)->setY(thirdBase->y());
                    keeper->setThird(playersOnField.at(0)->getPlayer());
                    playersOnField.at(1)->setX(secondBase->x()); playersOnField.at(1)->setY(secondBase->y());
                    keeper->setSecond(playersOnField.at(1)->getPlayer());
                    playersOnField.at(2)->setX(firstBase->x()); playersOnField.at(2)->setY(firstBase->y());
                    keeper->setFirst(playersOnField.at(2)->getPlayer());
                }
            }
            else if(keeper->whosOnThird()!=0){
                playersOnField.at(1)->setX(secondBase->x()); playersOnField.at(1)->setY(secondBase->y());
                keeper->setSecond(playersOnField.at(1)->getPlayer());
                playersOnField.at(2)->setX(firstBase->x()); playersOnField.at(2)->setY(firstBase->y());
                keeper->setFirst(playersOnField.at(2)->getPlayer());
            }
            else{
                playersOnField.at(0)->setX(secondBase->x()); playersOnField.at(0)->setY(secondBase->y());
                keeper->setSecond(playersOnField.at(0)->getPlayer());
                playersOnField.at(1)->setX(firstBase->x()); playersOnField.at(1)->setY(firstBase->y());
                keeper->setFirst(playersOnField.at(1)->getPlayer());
            }
        }
        else{
            playersOnField.at(playersOnField.size()-1)->setX(firstBase->x()); playersOnField.at(playersOnField.size()-1)->setY(thirdBase->y());
            keeper->setFirst(playersOnField.at(0)->getPlayer());
        }
    }
    updateValues();
    ui->pitchGroupBox->setVisible(false);
    ui->pitchButton->setVisible(true);

    if(keeper->isGameOver()){
        endGame();
    }
}

//updates widgets
void ScoreKeeperScreen::pitch(){
    undoer->saveState(keeper, &playersOnField);
    ui->pitchGroupBox->setVisible(true);
    ui->pitchButton->setVisible(false);
    manageBases();
}

//updates widgets
void ScoreKeeperScreen::ballInPlay(){
    ui->inPlayGroupBox->setVisible(true);
    ui->pitchGroupBox->setVisible(false);
}

//clears the bases, adds runs
void ScoreKeeperScreen::homerun(){
    undoer->saveState(keeper, &playersOnField);
    keeper->homerun();
    updateValues();
    for(int i=0; i<playersOnField.size();i++){
        PlayerIcon* currentPlayer=playersOnField.at(i);
        currentPlayer->~QGraphicsItem();
        playersOnField.removeAt(i);
        i--;
    }
    ui->pitchButton->setVisible(true);
    ui->inPlayGroupBox->setVisible(false);
    if(keeper->isGameOver()){
        endGame();
    }
}

void ScoreKeeperScreen::single(){
    undoer->saveState(keeper, &playersOnField);
    spawnPlayer();
    keeper->single();
    updateValues();
    ui->pitchButton->setVisible(true);
    ui->inPlayGroupBox->setVisible(false);
}

void ScoreKeeperScreen::hitDouble(){
    undoer->saveState(keeper, &playersOnField);
    spawnPlayer();
    keeper->hitDouble();
    updateValues();
    ui->pitchButton->setVisible(true);
    ui->inPlayGroupBox->setVisible(false);
}

void ScoreKeeperScreen::triple(){
    undoer->saveState(keeper, &playersOnField);
    spawnPlayer();
    keeper->triple();
    updateValues();
    ui->pitchButton->setVisible(true);
    ui->inPlayGroupBox->setVisible(false);
}

void ScoreKeeperScreen::out(){
    undoer->saveState(keeper, &playersOnField);
    keeper->incrementOuts();
    if(keeper->isGameOver()){
        endGame();
    }

    if(keeper->getOuts()!=0){
        keeper->incrementLineupPosition();
    }
    updateValues();
    ui->pitchButton->setVisible(true);
    ui->inPlayGroupBox->setVisible(false);
    if(keeper->getOuts()==0){
        for(int i=0; i<playersOnField.size();i++){
            PlayerIcon* currentPlayer=playersOnField.at(i);
            currentPlayer->~QGraphicsItem();
            playersOnField.removeAt(i);
            i--;
        }
    }

}

void ScoreKeeperScreen::viewStats(){
    ViewPlayerStats* screen= new ViewPlayerStats(keeper->getHomeLineup(), keeper->getHomeStats(), keeper->getAwayLineup(), keeper->getAwayStats());
    screen->show();
}

void ScoreKeeperScreen::spawnPlayer(){
    PlayerIcon *icon= new PlayerIcon(keeper->whosAtBat());
    playersOnField.append(icon);
    theScene->addItem(icon);
}

void ScoreKeeperScreen::manageBases(){
    for(int i=0;i<playersOnField.size();i++){
        PlayerIcon* currentPlayer= playersOnField.at(i);
        if(currentPlayer->collidesWithItem(firstBase)){
            keeper->setFirst(currentPlayer->getPlayer());
            currentPlayer->placeOnFirst();
        }
        else if(currentPlayer->collidesWithItem(secondBase)){
            keeper->setSecond(currentPlayer->getPlayer());
            currentPlayer->placeOnSecond();

        }
        else if(currentPlayer->collidesWithItem(thirdBase)){
            keeper->setThird(currentPlayer->getPlayer());
            currentPlayer->placeOnThird();
        }
        else if(currentPlayer->collidesWithItem(homeBase)){

            keeper->addToScore(1);
            keeper->attributeRun(currentPlayer->getPlayer());
            keeper->attributeRBI();
            updateKeeperBases(playersOnField.at(i)->getPlayer());
            playersOnField.removeAt(i);
            i--;
            currentPlayer->~QGraphicsItem();
        }
        else{
            updateKeeperBases(playersOnField.at(i)->getPlayer());
            playersOnField.removeAt(i);
            i--;
            currentPlayer->~QGraphicsItem();
            keeper->incrementOuts();
            if(keeper->getOuts()==0){
                updateValues();
                for(int i=0; i<playersOnField.size();i++){
                    PlayerIcon* p= playersOnField.at(i);
                    p->~QGraphicsItem();
                    playersOnField.removeAt(i);
                    i--;
                }
            }
        }

    }
    updateValues();
    if(keeper->isGameOver()){
        endGame();
    }
}

void ScoreKeeperScreen::updateKeeperBases(Player* p){
    if(keeper->whosOnFirst()==p){
        keeper->setFirst(0);
    }
    else if(keeper->whosOnSecond()==p){
        keeper->setSecond(0);
    }
    else if(keeper->whosOnThird()==p){
        keeper->setThird(0);
    }
}

void ScoreKeeperScreen::undo(){

   ScoreKeeper* tempKeeper = undoer->getLastKeeper();

   if(tempKeeper != 0){
       this->keeper = tempKeeper;
   }

   for(int i=0; i<playersOnField.size(); i++){
       playersOnField.at(i)->~QGraphicsItem();
   }

   //places players back on the bases
   QList<PlayerIcon*>* tempList= undoer->getLastPlayers();
   if(tempList != 0){
       this->playersOnField = *tempList;
   }
   for(int i=0; i<playersOnField.size(); i++){
       int base = playersOnField.at(i)->getCurrentBase();
       if(base==1){
           playersOnField.at(i)->placeOnFirst();
       }
       else if(base==2){
           playersOnField.at(i)->placeOnSecond();
       }
       else if(base==3){
           playersOnField.at(i)->placeOnThird();
       }
   }

   for(int i=0; i<playersOnField.size(); i++){
       theScene->addItem(playersOnField.at(i));
   }

   updateValues();
}

void ScoreKeeperScreen::endGame(){
    GameOverScreen* gos = new GameOverScreen(keeper);
    gos->show();
    this->hide();
}
